package com.github.hgkmail.hello.cmd;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

import static java.lang.System.out;

/**
 * 递归替换文件内容和文件名
 *
 * @author kimhuang
 * @date 2021/2/12
 */
public class BatchReplace {

    /**
     * 项目根目录
     */
    private String baseDir = "/Users/hgkmail-mb/Downloads/kwitter456";
    /**
     * 旧字符串
     */
    private String fromStr = "Twitter456";
    /**
     * 新字符串
     */
    private String toStr = "Kwitter456";
    /**
     * 排除的目录
     */
    private String[] excludeDir = new String[]{".git", ".mvn", ".gradle", "target", "out", "build", "logs"};
    /**
     * 排除的文件
     */
    private String[] excludeFile = new String[]{".gitignore", "mvnw", "mvnw.cmd", "gradlew", "gradlew.bat"};
    /**
     * 是否打印修改的地方
     */
    private boolean printModify = true;

    public static void main(String[] args) {
        new BatchReplace().run();
    }

    public void run() {
        dfsDir(new File(baseDir), this::processFile);
    }

    private void dfsDir(File dir, Function<File, File> listen) {
        if (dir == null || listen == null) {
            return;
        }
        if (Arrays.asList(excludeDir).contains(dir.getName())) {
            return;
        }
        File[] fileList = dir.listFiles();
        if (fileList == null || fileList.length <= 0) {
            return;
        }

        for (File one : fileList) {
            if (one.isFile()) {
                listen.apply(one);
            } else {
                File changeDir = listen.apply(one);
                dfsDir(changeDir != null ? changeDir : one, listen);
            }
        }
    }

    /**
     * 处理函数，如果目录名变化，返回新的目录
     *
     * @param file
     * @return
     */
    private File processFile(File file) {
        replaceContent(file);
        return replaceName(file);
    }

    /**
     * 替换文件名
     *
     * @param file
     */
    private File replaceName(File file) {
        if (file == null) {
            return null;
        }
        String fileName = file.getName();
        if (!fileName.contains(fromStr)) {
            return null;
        }

        boolean isFile = file.isFile();
        String isFileStr = isFile ? "[file]" : "[dir]";

        String changeFileName = file.getParent() + File.separator + fileName.replaceAll(fromStr, toStr);
        File changeFile = new File(changeFileName);
        boolean res = file.renameTo(changeFile);
        assert res : "重命名失败: " + isFileStr + fileName;

        if (printModify) {
            out.println("rename: " + isFileStr + file.getAbsolutePath());
        }

        return isFile ? null : changeFile;
    }

    /**
     * 替换文件内容
     *
     * @param file
     */
    private void replaceContent(File file) {
        if (!file.isFile()) {
            return;
        }
        if (Arrays.asList(excludeFile).contains(file.getName())) {
            return;
        }

        List<String> lines = null;
        try {
            lines = FileUtils.readLines(file, StandardCharsets.UTF_8);
            int lineCount = lines.size();
            for (int i = 0; i < lineCount; i++) {
                String lineStr = lines.get(i);
                if (lineStr.contains(fromStr)) {
                    if (printModify) {
                        out.println(file.getAbsolutePath() + ": " + lineStr);
                    }
                    String temp = lineStr.replaceAll(fromStr, toStr);
                    lines.set(i, temp);
                }
            }
            FileUtils.writeLines(file, StandardCharsets.UTF_8.name(), lines, false);
        } catch (Exception e) {
            out.println("replaceContent出错: " + e.getMessage());
            e.printStackTrace();
        }
    }

}
